package com.marktrace.controller;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.marktrace.entity.DLocation;
import com.marktrace.service.LocationService;
import com.marktrace.util.DateUtils;
import com.marktrace.util.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Controller
@Slf4j
public class IndexController extends BaseController{

    private static final String AUTH_TOKEN = "marktrace";
    private static final String DATAMAPKEY = "datamapkey";
    private static final String LNOSETKEY = "lnoset";
    private static final String TIMEHOUR = "timeHour";
    private static final String TIMEMINUTE = "timeMinute";
    private static final String TIMELISTKEY = "timelist";

    @Autowired
    private StringRedisTemplate srt;
    @Autowired
    private LocationService locationService;
    @Autowired
    private RedisTemplate redisTemplate;



    @RequestMapping("/index")
    public String index(){
        return "pulldata.html";
    }

    @RequestMapping("/list")
    @ResponseBody
    public R list(HttpServletRequest request){
        Page page = getPage(request);
        Map<String,Object> map = new HashMap<>(2);
        String endtime = request.getParameter("endtime")==null?"":request.getParameter("endtime");
        if(endtime.isEmpty()){
            endtime = DateUtils.getDate("yyyy-MM-dd HH:mm");
        }
        String frequency = request.getParameter("frequency")==null?"":request.getParameter("frequency");
        if(frequency.isEmpty()){
            frequency = "1";
        }
        Date startDate = DateUtils.addMinutes(DateUtils.parseDate(endtime),-Integer.valueOf(frequency));
        Date endDate = DateUtils.addSeconds(DateUtils.parseDate(endtime),-1);
        map.put("starttime",DateUtils.formatDateTime(startDate));
        map.put("endtime",DateUtils.formatDateTime(endDate));
        locationService.selectAllMap(map);
        return R.list(page);
    }

    @RequestMapping("/detail")
    @ResponseBody
    public R detail(HttpServletRequest request){
        Page page = getPage(request);
        Map<String,Object> map = new HashMap<>(3);
        String endtime = request.getParameter("endtime")==null?"":request.getParameter("endtime");
        if(endtime.isEmpty()){
            endtime = DateUtils.getDate("yyyy-MM-dd HH:mm")+":59";
        }
        String frequency = request.getParameter("frequency")==null?"":request.getParameter("frequency");
        if(frequency.isEmpty()){
            frequency = "1";
        }
        String eqno = request.getParameter("eqno")==null?"":request.getParameter("eqno");
        Date startDate = DateUtils.addSeconds(DateUtils.parseDate(endtime),-59);
        map.put("starttime",DateUtils.formatDateTime(startDate));
        map.put("endtime",endtime);
        map.put("eqno",eqno);
        locationService.selectDetail(map);
        return R.list(page);
    }

    @Scheduled(cron="0 0/1 * * * ?")
    public synchronized void handlerData(){
        String nowTime = DateUtils.getDateTime();
        log.info("当前时间:"+nowTime);
        List<DLocation> list = getDataFromRedis(nowTime);
        writeIntoDB(list);
    }

    /**
     * 从redis中获取数据
     * @return
     */
    public List<DLocation> getDataFromRedis(String nowTime){
        Set<String> keySets = redisTemplate.keys("lb:*");
        List<DLocation> list = new ArrayList<>();
        if(!keySets.isEmpty()){
            //当前时间戳
            long nowTimestamp = DateUtils.dateToStamp(nowTime)/1000-1;
            //当前时间的上一分钟的时间戳
            long lastTimestamp = nowTimestamp-59;
            DLocation dLocation;
            for(String key:keySets){
                Set<String> dataSet = srt.opsForZSet().rangeByScore(key,lastTimestamp,nowTimestamp);
                if(!dataSet.isEmpty()){
                    Object[] objectArrays= dataSet.toArray();
                    Map<String,Object> map = (Map<String, Object>) JSON.parse(objectArrays[0].toString());
                    String lno = map.get("lid").toString();
                    String eqno = map.get("eqid").toString();
                    dLocation = new DLocation();
                    dLocation.setLno(lno);
                    dLocation.setEqno(eqno);
                    dLocation.setUploadtime(DateUtils.parseDate(map.get("enddate").toString()));
                    list.add(dLocation);
                }
            }
            delDateFromRedis(keySets,lastTimestamp,nowTimestamp);
        }
        return list;
    }

    /**
     * 数据入库
     * @return
     */
    private int writeIntoDB(List<DLocation> list){
        List<DLocation> filterList = new ArrayList<>();
        int i = 0;
        if(list.size()>0){
            list.stream().forEach(
                    d -> {
                        if(!filterList.contains(d)){
                            filterList.add(d);
                        }
                    }
            );
            i = locationService.insertBatch(filterList);
            log.info("数据入库:"+i+"条记录");
        }
        return i;
    }

    /**
     * 删除redis中的数据
     * @param lastTimestamp
     * @param nowTimestamp
     * @return
     */
    private void delDateFromRedis(Set<String> keys ,long lastTimestamp,long nowTimestamp){
        for(String key:keys){
            redisTemplate.opsForZSet().removeRangeByScore(key,lastTimestamp,nowTimestamp);
        }
    }

    /**
     * 接收硬件数据
     * 数据模拟eg: http://192.168.1.2:8080/pullData?TOKEN=marktrace&DEVICE=0460056456765456&LABEL=1556455&TIME=2019-1-23%2014:24:03
     * @param request
     * @return
     */
    @RequestMapping("/pullData")
    @ResponseBody
    public R pullData(HttpServletRequest request){
        Map<String, Object> map = getRequestParamMap(request);
        System.out.println("接收到的数据:" + map);
        DLocation dLocation;
        int i = 0;
        String TOKEN = map.get("TOKEN").toString();
        if (!AUTH_TOKEN.equals(TOKEN)) {
            return R.error("no auth!");
        }
        String uploadtime = "";
        if (map.get("TIME") != null) {
            uploadtime = map.get("TIME").toString();
            initTime(uploadtime, false);
        } else {
            return R.error("time is not null");
        }
        String str_timeHour = redisTemplate.opsForValue().get(TIMEHOUR).toString();
        String str_timeMinute = redisTemplate.opsForValue().get(TIMEMINUTE).toString();
        //时间判断
        if (str_timeHour.equals(DateUtils.getDate(uploadtime, "HH"))) {
            if (str_timeMinute.equals(DateUtils.getDate(uploadtime, "mm"))) {
                String lno = map.get("LABEL").toString();
                String eqno = map.get("DEVICE").toString();
                dLocation = new DLocation();
                dLocation.setLno(lno);
                dLocation.setEqno(eqno);
                dLocation.setUploadtime(DateUtils.parseDate(uploadtime));
                redisTemplate.opsForSet().add(LNOSETKEY, lno);

                Set<DLocation> set = redisTemplate.opsForSet().members(TIMELISTKEY);
                int size = set.size();
                set.add(dLocation);
                int endSize = set.size();
                if (size != endSize) {
                    redisTemplate.opsForSet().add(TIMELISTKEY, dLocation);
                }

            } else {
                initTime(uploadtime, true);
                if (i > 0) {
                    return R.ok();
                } else {
                    return R.error();
                }
            }
        } else {
            initTime(uploadtime, true);
        }
        return R.ok();
    }

    /**
     * 初始化时分秒,以便后面做判断
     * @param uploadtime
     * @param flag:true用于重新初始化时间
     */
    private void initTime(String uploadtime,boolean flag){
        if(redisTemplate.hasKey(TIMEHOUR) && redisTemplate.hasKey(TIMEMINUTE)){
            String str_timeHour = redisTemplate.opsForValue().get(TIMEHOUR).toString();
            String str_timeMinute = redisTemplate.opsForValue().get(TIMEMINUTE).toString();
            if(str_timeHour.isEmpty() || flag){
                redisTemplate.opsForValue().set(TIMEHOUR,DateUtils.getDate(uploadtime,"HH"));
            }
            if(str_timeMinute.isEmpty() || flag){
                redisTemplate.opsForValue().set(TIMEMINUTE,DateUtils.getDate(uploadtime,"mm"));
            }
        }else{
            redisTemplate.opsForValue().set(TIMEHOUR,DateUtils.getDate(uploadtime,"HH"));
            redisTemplate.opsForValue().set(TIMEMINUTE,DateUtils.getDate(uploadtime,"mm"));
        }
    }


}
